import fs from 'node:fs';
import path from 'node:path';
import {
  CommonRiskLevel,
  HeatstrokeRiskLevel,
  IWeatherWarningContent,
  PollenRiskLevel,
  WeatherFileType,
} from './weather.model';
import dayjs from 'dayjs';

/**
 * 尝试用不同编码解码内容
 * @param buffer 文件Buffer
 * @returns 解码后的字符串
 */
function decodeChineseContent(buffer: Buffer): string {
  // 尝试不同的编码方式，从常见的中文编码开始
  const encodings = ['utf8', 'gbk', 'gb2312', 'big5'];
  try {
    // 与ip.util.ts中的处理方式一致
    // axios中返回的是ArrayBuffer，这里需要注意类型处理
    const decoder = new TextDecoder('gbk');
    return decoder.decode(buffer as any);
  } catch (error) {
    // 如果GBK解码失败，回退到UTF-8
    return buffer.toString('utf8');
  }
}

const matchFileTypeName = (fileName: string): { name: string; type: string } => {
  const typeList = [
    { type: 'lngm', name: '老年人感冒气象风险' },
    { type: 'lrgm', name: '老年人感冒气象风险' },
    { type: 'qngm', name: '成人感冒气象风险' },
    { type: 'zs', name: '中暑气象风险' },
    { type: 'copd', name: '慢阻肺气象环境风险' },
    { type: 'crgm', name: '儿童感冒气象风险' },
    { type: 'POLLEN', name: '花粉指数' },
  ];

  const type = typeList.find((item) => fileName.includes(item.type));

  if (type) {
    return { name: type.name, type: type.type };
  } else {
    return { name: '未知类型', type: 'unknown' };
  }
};

const matchRiskLevel = (
  type: string,
  riskLevel: string
): CommonRiskLevel | HeatstrokeRiskLevel | PollenRiskLevel | string => {
  switch (type) {
    case 'lngm':
    case 'lrgm':
    case 'qngm':
    case 'crgm':
    case 'copd': {
      return CommonRiskLevel[riskLevel as keyof typeof CommonRiskLevel];
    }
    case 'zs': {
      return HeatstrokeRiskLevel[riskLevel as keyof typeof HeatstrokeRiskLevel];
    }
    case 'POLLEN': {
      return PollenRiskLevel[riskLevel as keyof typeof PollenRiskLevel];
    }
    default: {
      return '';
    }
  }
};

const getTodayDate = (): string => {
	return dayjs().format('YYYYMMDD');
}

// 判断文件名中的日期是否为明天
function getWeatherFileTypeByFileName(fileName: string): WeatherFileType {
  const dateMatch = fileName.match(/(\d{8})/);
  if (!dateMatch) return WeatherFileType.TODAY;
  const fileDateStr = dateMatch[1];
  const fileDate = new Date(
    Number(fileDateStr.slice(0, 4)),
    Number(fileDateStr.slice(4, 6)) - 1,
    Number(fileDateStr.slice(6, 8))
  );
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const tomorrow = new Date(today);
  tomorrow.setDate(today.getDate() + 1);
  if (
    fileDate.getFullYear() === tomorrow.getFullYear() &&
    fileDate.getMonth() === tomorrow.getMonth() &&
    fileDate.getDate() === tomorrow.getDate()
  ) {
    return WeatherFileType.TOMORROW;
  }
  return WeatherFileType.TODAY;
}

const formatWeatherContent = (fileName: string, content: string): IWeatherWarningContent => {
  const isTomorrow = getWeatherFileTypeByFileName(fileName);

  if (fileName.includes('POLLEN')) {
    const regex = /^(.+?)\r\n(\d{4}-\d{2}-\d{2})\r\n等级：(.+?)\r\n防护建议：(.+?)\r\n$/;

    const match = content.match(regex);

    const { type, name } = matchFileTypeName(fileName);

    const riskLevel = matchRiskLevel(type, match[3]);

    const result = {
      fileName,
      type: String(type).toUpperCase(), // 自定义标识符，符合你之前的风格
      name,
      disease: match[1],
      date: dayjs().format('YYYY-MM-DD'), // 花粉指数没有日期，使用当前日期
      riskLevel,
      riskLevelName: match[3], // 风险等级名称
      vulnerableGroups: '', // 花粉指数没有防范人群
      advice: match[4],
      isTomorrow,
    };

    return result;
  }

  const regex =
    /^(.+?)\r\n(\d{4}-\d{2}-\d{2})\r\n气象风险等级：(.+?)\r\n(?:防范人群：(.+?)\r\n)?预防建议：(.+?)\r\n$/;

  const match = content.match(regex);

  const { type, name } = matchFileTypeName(fileName);

  const riskLevel = matchRiskLevel(type, match[3]);

  if (match) {
    const result = {
      fileName,
      name,
      type: String(type).toUpperCase(), // 自定义标识符，符合你之前的风格
      disease: match[1], // 疾病名称
      date: dayjs().format('YYYY-MM-DD'), // 日期
      riskLevel, // 风险等级
      riskLevelName: match[3], // 风险等级名称
      vulnerableGroups: match[4] ?? '', // 防范人群
      advice: match[5], // 预防建议
      isTomorrow,
    };

    return result;
  } else {
    console.log('No match found.');
    return {} as IWeatherWarningContent; // 返回一个空对象或处理错误
  }
};

const readFilesByDateDir = async (dirPath: string): Promise<string[]> => {
  const result: string[] = [];
  const files = await fs.promises.readdir(dirPath);

  // 获取当天日期字符串，格式为yyyyMMdd
	const currentDate = getTodayDate();

	for (const file of files) {
    const filePath = path.join(dirPath, file);
    const stats = await fs.promises.stat(filePath);

    // 只查找与当天日期相同的文件夹
    if (stats.isDirectory() && file === `${currentDate}11`) {
			console.log(`正在读取目录: ${filePath}`);
      const subFiles = await fs.promises.readdir(filePath);
			console.log(`找到 ${subFiles.length} 个子文件/文件夹`, subFiles);
      for (const subFile of subFiles) {
        const subFilePath = path.join(filePath, subFile);
        const subStats = await fs.promises.stat(subFilePath);
        if (subStats.isFile()) {
          result.push(subFilePath); // 返回完整路径
        }
      }
    }
  }

	// 只保留以 pd_ 开头的文件路径
	return result.filter(filePath => path.basename(filePath).startsWith('pd_'));
};

const readFileByPollen = async (dirPath: string): Promise<string> => {
	// 读取文件夹下的文件
	let result = '';
	const files = await fs.promises.readdir(dirPath);
	const currentDate = getTodayDate();

	for (const file of files) {
		const filePath = path.join(dirPath, file);
    const stats = await fs.promises.stat(filePath);

		if (stats.isFile() && file.startsWith('POLLEN') && file.includes(currentDate)) {
			result = filePath
		}
	}

	return result;
}

export const readFileByPath = async (dirPath: string): Promise<IWeatherWarningContent[]> => {
  if (!fs.existsSync(dirPath)) {
    throw new Error(`目录不存在: ${dirPath}`);
  }

  const files: any[] = await readFilesByDateDir(dirPath);
	const file = await readFileByPollen(dirPath);

	if (file) {
		files.push(file);
	}

  const results: any[] = [];

  for (const file of files) {
    const stats = fs.statSync(file);

    if (stats.isFile()) {
      const buffer = fs.readFileSync(file);
      const content = decodeChineseContent(buffer);
      const fileName = path.basename(file);
      results.push(formatWeatherContent(fileName, content));
    }
  }

  return results;
};
